package com.example.demo.mq.service;

import com.example.demo.config.artemis.ActiveMqManager;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import java.util.Arrays;
import java.util.Date;
import java.util.EnumSet;

@Component
public class MessagingService {
    private final static Logger logger = LoggerFactory.getLogger(MessagingService.class);
    @Autowired
    private JmsTemplate jmsTemplate;

    private Boolean stopFlag = Boolean.FALSE;

    public static void main(String[] args) throws Exception {
        sendMailMessageByCore();
    }

    public static void sendMailMessageByCore() throws Exception {
        String text = "PRODUCER:- ";
        ServerLocator serverLocator = null;
        ClientSessionFactory factory = null;
        ClientSession session = null;
        String queueName = "jinxin_queue_02";
        String addressName = "jinxin_address_01";

        try {
            serverLocator = ActiveMQClient.createServerLocator("tcp://127.0.0.1:61616");
            serverLocator.setPreAcknowledge(Boolean.TRUE);
            factory = serverLocator.createSessionFactory();
            session = factory.createSession();
            ClientSession.QueueQuery queueQuery =
                    session.queueQuery(new SimpleString(queueName));

            if(!queueQuery.isExists()) {
                ClientSession.AddressQuery addressQuery = session.addressQuery(new SimpleString(addressName));
                if(!addressQuery.isExists()) {
                    RoutingType[] types = {
                            RoutingType.ANYCAST,
                            RoutingType.MULTICAST
                    };
                    EnumSet<RoutingType> set = EnumSet.copyOf(Arrays.asList(types));

                    session.createAddress(new SimpleString(addressName),
                            set,
                            false);
                }
                QueueConfiguration queueConfiguration =
                        new QueueConfiguration(queueName);
                queueConfiguration.setAddress(addressName);
                queueConfiguration.setRoutingType(RoutingType.MULTICAST);
                queueConfiguration.setDurable(true);
                //queueConfiguration.setLastValue(true);
                //queueConfiguration.setExclusive(true);
                //queueConfiguration.setAutoDelete(true);
                //queueConfiguration.setDurable(false);
                session.createQueue(queueConfiguration);
                logger.debug("Queue name is created with address.");
            }

            session.start();
            ClientProducer producer = session.createProducer(addressName);
            while(true) {
                String msg = "PRODUCER-CORE: " + new Date();
                logger.debug(msg);
                Thread.sleep(2000);
                ClientMessage message = session.createMessage(true);
                message.setExpiration(System.currentTimeMillis() + 3000 * 1000);
                message.getBodyBuffer().writeString(msg);
                producer.send(message);
            }

        } catch (Exception e) {
            logger.error("Failed to create client session factory, reason: {}", e.getMessage());
        } finally {
            if(session != null) {
                session.close();
            }
            if(factory != null) {
                factory.close();
            }
        }
    }

    public void sendMailMessage() {
        String text = "PRODUCER:- ";
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                while(!stopFlag) {
                    try {
                        Thread.sleep(2000);
                        // here should use address name; take long time to check.;;;
                        // please take care of it if queue name and address name are not same.
                        jmsTemplate.convertAndSend("jinxin_address_01", text + new Date());
                    } catch (Exception e) {
                        logger.error("Failed to send message to MQ, reason: {}", e.getMessage());
                    }

                }
            }
        }, "producer-" + System.currentTimeMillis());
        t.setDaemon(true);
        t.start();
    }

    @PreDestroy
    public synchronized void stopSignal() {
        stopFlag = true;
    }
}